/*
 * PrjSvnManager.java
 *
 * Copyright (c) 2008 Teamnet. All Rights Reserved.
 *
 * This source file may not be copied, modified or redistributed,
 * in whole or in part, in any form or for any reason, without the express
 * written consent of Teamnet.
 */

package ro.prj.manager.svn;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.BasicAuthenticationManager;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;



/**
 * This class is used to todo
 */
public class PrjSvnManager {

    private static Log log = LogFactory.getLog(PrjSvnManager.class);
    private SVNSecure svnProperty;


    private PrjSvnManager(SVNSecure svnProperty) {

        this.svnProperty = svnProperty;
    }

    public synchronized static PrjSvnManager instance(SVNSecure svnProperty) {
        setupLibrary();
        return new PrjSvnManager(svnProperty);
    }

    public synchronized static PrjSvnManager instanceFromProperties(){
        SVNSecure secure= SVNSecure.loadFromBundle();
        return instance(secure);

    }






    public void doSvnDirs(String svnDirPath) throws SVNException {
//        svnDirPath=svnDirPath.replaceAll("//","/");
        SVNRepository repo=repository();
        List<String> nodes=SVNUtil.parseFullNodesToDir(svnDirPath);
        int p=0;
        for(String node:nodes){
            SVNNodeKind nodeKind = repo.checkPath(node,-1);
            if(nodeKind==SVNNodeKind.NONE){
                ISVNEditor editor=repo.getCommitEditor("directory and file added",null);
                if(p==0){
                    editor.openRoot(-1);
                }else{
                    editor.openRoot(-1);
                    for(int i=0;i<p;i++){
                        editor.openDir(nodes.get(i),-1);
                    }
                }


                editor.addDir(node,null,-1);
                editor.closeDir();
                editor.closeEdit();
            }
            p++;
        }

    }

    public void doSvnFile(String svnDirPath,String fileName,byte[] content) throws SVNException, PrjSvnException {
        doSvnDirs(svnDirPath);
        SVNRepository repo=repository();
        List<String> nodes=SVNUtil.parseFullNodesToDir(svnDirPath);
        SVNNodeKind kind=repo.checkPath(svnDirPath+"/"+fileName,-1);
        ISVNEditor editor=repo.getCommitEditor("directory and file added",null);
        editor.openRoot(-1);
        for(String node:nodes){
            editor.openDir(node,-1);
        }
        String checksum;
        if(kind==SVNNodeKind.FILE){
            editor.openFile(svnDirPath+"/"+fileName, -1);
            editor.applyTextDelta(svnDirPath+"/"+fileName, null);
            SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
            checksum = deltaGenerator.sendDelta(svnDirPath+"/"+fileName, new ByteArrayInputStream(readFile(svnDirPath+"/"+fileName).toByteArray())
                    , 0, new ByteArrayInputStream(content), editor, true);

        }else{
            editor.addFile(svnDirPath+"/"+fileName,null,-1);
            editor.applyTextDelta(svnDirPath+"/"+fileName,null);
            SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
            checksum = deltaGenerator.sendDelta(svnDirPath+"/"+fileName, new ByteArrayInputStream(content), editor, true);
        }

        editor.closeDir();
        editor.closeFile(svnDirPath+"/"+fileName, checksum);
        editor.closeEdit();

    }

    public void modifSvnFile(String svnDirPath,String fileName,byte[] content,String replacer) throws SVNException, PrjSvnException {
        
    }

     public void doSvnFile(String svnDirPath,String fileName, InputStream content) throws SVNException, PrjSvnException {
        doSvnDirs(svnDirPath);
        SVNRepository repo=repository();
        List<String> nodes=SVNUtil.parseFullNodesToDir(svnDirPath);
        SVNNodeKind kind=repo.checkPath(svnDirPath+"/"+fileName,-1);
        ISVNEditor editor=repo.getCommitEditor(null,null);
        editor.openRoot(-1);
        for(String node:nodes){
            editor.openDir(node,-1);
        }
        String checksum;
        if(kind==SVNNodeKind.FILE){
            editor.openFile(svnDirPath+"/"+fileName, -1);
            editor.applyTextDelta(svnDirPath+"/"+fileName, null);
            SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
            checksum = deltaGenerator.sendDelta(svnDirPath+"/"+fileName, new ByteArrayInputStream(readFile(svnDirPath+"/"+fileName).toByteArray())
                    , 0,content, editor, true);

        }else{
            editor.addFile(svnDirPath+"/"+fileName,null,-1);
            editor.applyTextDelta(svnDirPath+"/"+fileName,null);
            SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
            checksum = deltaGenerator.sendDelta(svnDirPath+"/"+fileName, content, editor, true);
        }

        editor.closeDir();
        editor.closeFile(svnDirPath+"/"+fileName, checksum);
        editor.closeEdit();

    }



    public ByteArrayOutputStream readFile(String filePath) throws PrjSvnException {
         SVNProperties fileProperties = new SVNProperties();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();

         try {
            SVNNodeKind nodeKind = repository().checkPath(filePath, -1);

            if (nodeKind == SVNNodeKind.NONE) {
                return null;
            } else if (nodeKind == SVNNodeKind.DIR) {
                throw new PrjSvnException("The entry at '" + svnProperty.getUrl()
                        + "' is a directory while a file was expected.");
            }

            repository().getFile(filePath, -1, fileProperties, baos);

        } catch (SVNException svne) {
            throw new PrjSvnException("error while fetching the file contents and properties: " + svne.getMessage());
        }
        return baos;
    }




    private SVNRepository repository() {
        SVNRepository repository = null;
        try {
            repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(svnProperty.getUrl()));

            BasicAuthenticationManager bam=new BasicAuthenticationManager(svnProperty.getName(),svnProperty.getPassword());
            ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(svnProperty.getName(),
                    svnProperty.getPassword());

            repository.setAuthenticationManager(bam);

        } catch (SVNException svne) {
            log.error("Wrror while creating an repository for the location '"
                    + svnProperty.getUrl() + "': " + svne.getMessage());

        }
        return repository;
    }



    private static void setupLibrary() {
        DAVRepositoryFactory.setup();
        SVNRepositoryFactoryImpl.setup();
        FSRepositoryFactory.setup();
    }



    public SVNSecure getSvnProperty() {
        return svnProperty;
    }

    public void setSvnProperty(SVNSecure svnProperty) {
        this.svnProperty = svnProperty;
    }

      public static void main(String[] args) {
        PrjSvnManager inst=instanceFromProperties();
        try {
            ByteArrayOutputStream baos=inst.readFile("backend/src/main/resources/ro/prjmanager/generator/template/web/menu.vm");
            String str=baos.toString().replace(" <!-- end submenu ${form.getGuiMenu()} -->","cucubau");


            

        }  catch (PrjSvnException e) {
            e.printStackTrace();
        }


    }



    
}
